# LeetCode 409、最长回文串
# 一、题目描述
给定一个包含大写字母和小写字母的字符串 s
,返回 通过这些字母构造成的 最长的回文串 。
在构造过程中,请注意 区分大小写 。比如 "Aa"
不能当做一个回文字符串。
示例 1:
输入:s = "abccccdd"
输出:7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
示例 2:
输入:s = "a"
输入:1
示例 3:
输入:s = "bb"
输入: 2
提示:
1 <= s.length <= 2000
s
只能由小写和/或大写英文字母组成
# 二、题目解析
# 三、参考代码
# 1、Java 代码
// 登录 AlgoMooc 官网获取更多算法图解
// https://www.algomooc.com
// 作者:程序员吴师兄
// 微信:wzb_3377
// 代码有看不懂的地方一定要私聊咨询吴师兄呀
// 最长回文串(LeetCode 409):https://leetcode.cn/problems/longest-palindrome/
class Solution {
public int longestPalindrome(String s) {
// 手动设置哈希表,哈希函数为 c - 'A'
// 这里的哈希表的作用是计数器
// 由于 大写字母 'A' 与小写字母 'a' 的 ASCII 相差 32
// A : 65
// a : 97
// 所以设置哈希表的大小为 32 + 26 = 58
int[] cnt = new int[58];
// 统计每个字母出现的频次
for (char c : s.toCharArray()) {
cnt[c - 'A'] += 1;
}
// 初始化结果
int ans = 0;
for (int x: cnt) {
// 根据奇偶性来判断当前字母的使用次数为多少
// 按位与:&
// 将参与运算的两操作数各对应的二进制位进行与操作
// 只有对应的两个二进位均为 1 时,结果的对应二进制位才为 1 ,否则为 0
// 通过这个方法判断 x 的奇偶性,即统计这个字母出现的是偶数次还是奇数次
// 1 的二进制为 0001
// 比如 x 为 4,二进制为 0100 ,那么 x & 1 的结果是 0000 ,即为 0
// 那么 x - (x & 1) 的结果是 4,那么这 4 个字母全部都可以出现在最终的回文串中
// **********
// 比如 x 为 5,二进制为 0101 ,那么 x & 1 的结果是 0001 ,即为 1
// 那么 x - (x & 1) 的结果是 4,即出现了 5 次的那个字母只有其中 4 个可以被用上
ans += x - (x & 1);
}
// 最后,会尝试一下,能不能再添加一个字符到回文串中
// 如果最终的长度小于原字符串的长度,说明里面某个字符出现了奇数次,那么那个字符可以放在回文串的中间,所以额外再加一
return ans < s.length() ? ans + 1 : ans;
}
}
# **2、**C++ 代码
class Solution {
public:
int longestPalindrome(string s) {
// 手动设置哈希表,哈希函数为 c - 'A'
// 这里的哈希表的作用是计数器
// 由于 大写字母 'A' 与小写字母 'a' 的 ASCII 相差 32
// A : 65
// a : 97
// 所以设置哈希表的大小为 32 + 26 = 58
int cnt[58] = {0};
// 统计每个字母出现的频次
for(string::size_type i = 0; i < s.size(); i++) {
if('a' <= s[i] && s[i] <= 'z') {
cnt[s[i]-'a']++;
} else {
cnt[s[i]-'A'+26]++;
}
}
// 初始化结果
int ans = 0;
for (int x: cnt) {
// 根据奇偶性来判断当前字母的使用次数为多少
// 按位与:&
// 将参与运算的两操作数各对应的二进制位进行与操作
// 只有对应的两个二进位均为 1 时,结果的对应二进制位才为 1 ,否则为 0
// 通过这个方法判断 x 的奇偶性,即统计这个字母出现的是偶数次还是奇数次
// 1 的二进制为 0001
// 比如 x 为 4,二进制为 0100 ,那么 x & 1 的结果是 0000 ,即为 0
// 那么 x - (x & 1) 的结果是 4,那么这 4 个字母全部都可以出现在最终的回文串中
// **********
// 比如 x 为 5,二进制为 0101 ,那么 x & 1 的结果是 0001 ,即为 1
// 那么 x - (x & 1) 的结果是 4,即出现了 5 次的那个字母只有其中 4 个可以被用上
ans += x - (x & 1);
}
// 最后,会尝试一下,能不能再添加一个字符到回文串中
// 如果最终的长度小于原字符串的长度,说明里面某个字符出现了奇数次,那么那个字符可以放在回文串的中间,所以额外再加一
return ans < s.length() ? ans + 1 : ans;
}
};
# 3、Python 代码
class Solution:
def longestPalindrome(self, s: str) -> int:
# 手动设置哈希表,哈希函数为 c - 'A'
# 这里的哈希表的作用是计数器
# 由于 大写字母 'A' 与小写字母 'a' 的 ASCII 相差 32
# A : 65
# a : 97
# 所以设置哈希表的大小为 32 + 26 = 58
l_s = list(s)
#字典来存储每个字母出现的个数
cnt = {}
for word in l_s:
cnt[word] = 0
for word in l_s:
cnt[word] += 1
ans = 0
for key, value in cnt.items():
#如果出现个数为偶数,直接加入
if value % 2 == 0:
ans += value
else:
#如果为奇数,则加value - 1,并且,该字母的次数变为1
ans += value - 1
cnt[key] = 1
return ans + 1 if 1 in cnt.values() else ans